class Person(object):
    def __init__(self,id,name,gender): #构造函数
        self.id=id   #定义类的属性并赋值
        self.name=name
        self.gender=gender
        self.__secret='这是一个秘密' #相当于java中private
    def info(self):
        print("Person",self.id,self.name,self.gender)
    def run(self):
        print("我会跑")
    def __str__(self):
        return "Persin类的对象%s"%self.name

zs=Person('001','张三','男')  # 创建对象
print(zs)
print(zs.id)
print(zs.name)
print(zs.gender)
print(zs._Person__secret) # 可以获取被封装的属性
zs.info()

class Teacher(Person):  # 继承Person类
    def __init__(self,id,name,gender):
        super(Teacher, self).__init__(id,name,gender) # 调用父类构造方法
        self.professional='compute'
    def info(self):
        print('Teacher',self.id,self.name,self.gender,self.professional)


t1 = Teacher("张老师", "24", "男")

class Student(Person):
    def __init__(self,id,name,gender):
        super(Student, self).__init__(id,name,gender)
        self.skill='play game'
    def info(self):
        print('Student',self.id,self.name,self.gender,self.skill)
    def run(self):
        print('跑得快')

stu1=Student(1,'李四','男')

#定义一个方法接收Person类型的参数，然后对run方法调用两次

def runTwice(person):
    person.run()
    person.run()

runTwice(zs)
runTwice(t1)
runTwice(stu1)

# 鸭子类型：只要长得像鸭子那么就是鸭子
# 更多的是关注变量有没有方法 并不会对变量做类型的检查

class Duck():
    def run(self):
        print('鸭子可会跑了')

dk=Duck()
runTwice(dk)

class Dog():
    pass
dog = Dog()


def run():
    print("狗也会跑")


# 猴子补丁
dog.run = run

runTwice(dog)
